package com.simafei.flow.core;

import cn.hutool.core.collection.CollectionUtil;
import com.simafei.flow.core.common.Criteria;
import com.simafei.flow.core.common.Predicate;
import lombok.Data;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 边
 * @author fengpengju
 */
@Data
public class Edge {

    /**
     * 线路Id
     */
    private String id;

    /**
     * from节点
     */
    private Node from;

    /**
     * to节点
     */
    private Node to;

    /**
     * 执行条件
     */
    private Criteria criteria;

    public EdgeResult execute(ExecutionContext context, List<Map<String, Object>> params) {
        long start = System.currentTimeMillis();
        Optional.ofNullable(context.getExecutionListener())
                .ifPresent(listener -> listener.beforeEdgeExecute(context, this));
        List<Map<String, Object>> results = doExecute(criteria, params);

        EdgeResult result = EdgeResult.builder().edgeId(id)
                .inputParams(params)
                .filteredParams(results)
                .pass(CollectionUtil.isNotEmpty(results))
                .spendTime(System.currentTimeMillis() - start)
                .build();

        context.collectResult(result);
        Optional.ofNullable(context.getExecutionListener())
                .ifPresent(listener -> listener.afterEdgeExecute(context, this, result));

        return result;
    }

    private List<Map<String, Object>> doExecute(Criteria criteria, List<Map<String, Object>> params) {
        if (Objects.isNull(criteria)) {
            return params;
        } else {
            return params.stream()
                    .filter(param -> Predicate.eval(criteria, param))
                    .collect(Collectors.toList());
        }
    }
}
